﻿using System;
using System.Collections.Generic;

namespace Csharp2048
{
    internal class Game2048
    {
        internal class Block
        {
            
            public int Num
            {
                get; set;
            }

            public Block()
            {
                
                Num = 0;
            }

            public bool Move(Block another_block)
            {
                if(Num!=0&&another_block.Num==0)
                {
                    another_block.Num = Num;
                    Num = 0;
                    return true;
                }
                return false;
            }
            public bool Merge(Block another_block)//把当前方块合并到另外一个方块去
            {

                if (Num!=0&& another_block.Num != 0&& another_block.Num == Num)//当前不为空
                {                 

                        another_block.Num += Num;
                        Num = 0;
                        //Console.WriteLine($"Merged: {Num} into {another_block.Num}");
                        return true;               
                }
                return false;
            }

            

            public void Show()
            {
                Console.Write($" [{Num,6}] ");
            }
        }

        private int Size;
        private List<List<Block>> Board;
        Random random;
        public Game2048(int size)
        {
            Size = size;
            Board = new List<List<Block>>();

            for (int i = 0; i < Size; i++)
            {
                List<Block> row = new List<Block>();
                for (int j = 0; j < Size; j++)
                {
                    row.Add(new Block());
                }
                Board.Add(row);
            }
            null_blocks = new List<ValueTuple<int, int>>();
            random = new Random();
        }

        bool need_to_recount_null_block = true;
        private List<ValueTuple<int, int>> null_blocks;

        void AddNullBlocksTOList()
        {
            null_blocks.Clear();
            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    if (Board[i][j].Num==0)
                    {
                        null_blocks.Add(new ValueTuple<int, int>(i, j));
                    }
                }
            }
        }
        public bool IsFull()
        {
            if (!need_to_recount_null_block) return null_blocks.Count == 0;
            AddNullBlocksTOList();
            return null_blocks.Count == 0;
        }

        public bool RandomAddNum()
        {
            if (need_to_recount_null_block)
            {
                AddNullBlocksTOList();
            }
            if (IsFull())
            {
                return false;
            }


            int random_num = random.Next(0, null_blocks.Count);
            int x = null_blocks[random_num].Item1;
            int y = null_blocks[random_num].Item2;
            Board[x][y].Num = 2;
            need_to_recount_null_block=true;
            //Console.WriteLine($"在({x},{y})添加了2");
            //Console.WriteLine($"{Board[x][y].is_null}");
            return true;
        }

        public void PrintBoardBool()
        {
            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    Console.Write($"[{Board[i][j].Num==0,6}]");

                }
                Console.WriteLine();
            }
        }

        public void PrintBoard()
        {
            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    Board[i][j].Show();
                }
                Console.WriteLine();
            }
        }

        List<ValueTuple<int, int, int, int>> BlocksMoveList =new List<ValueTuple<int, int, int, int>>();
        public void Merge(Direction direction)
        {
            BlocksMoveList.Clear();
            for (int i=1;i<Size;i++)//列
            {
                for (int j = 0; j < Size; j++)//行
                {
                    var block_move_list = new List<ValueTuple<int, int, int, int>>();
                    bool has_merged=false;
                    for(int k=0;k<i;k++)
                    {
                        ValueTuple<int, int, int, int> block_move;
                        int x, y, dx, dy;
                        if (direction == Direction.Left)
                        {
                            x = j; y = i - k; dx = 0; dy = -1;
                        }                     
                        else if (direction == Direction.Right)
                        {
                            x = j; y = Size - 1 - i + k; dx = 0; dy = 1;
                            
                        }                      
                        else if (direction == Direction.Up)
                        {
                            x = i - k; y = j; dx = -1; dy = 0;
                        }                          
                        else // (direction == Direction.Down)
                        {
                            x = Size - 1 - i + k; y = j; dx = 1; dy = 0;                                                  
                        }
                        if (Board[x][y].Move(Board[x+dx][y+dy]))
                        {
                            block_move_list.Add(new ValueTuple<int, int, int, int>(x, y, dx, dy));
                        }
                        else if(has_merged || Board[x][y].Merge(Board[x + dx][y + dy]))
                        {
                            block_move_list.Add(new ValueTuple<int, int, int, int>(x, y, dx, dy));
                            has_merged=true;
                        }
                            


                    }
                    //合并同方块的移动
                    for (int b = block_move_list.Count - 1; b > 0; b--)
                    {
                        var last = block_move_list[b-1];
                        var next = block_move_list[b];
                        if (last.Item1+ last.Item3== next.Item1 && last.Item2+ last.Item4== next.Item2)
                        {
                            block_move_list[b - 1] = new ValueTuple<int, int, int, int>(last.Item1, last.Item2, next.Item3 + last.Item3, next.Item4 + last.Item4);
                            block_move_list.RemoveAt(b);
                        }
                    }
                    BlocksMoveList.AddRange(block_move_list);
                }
            }
            
            
            need_to_recount_null_block = true;
        }

        public List<ValueTuple<int,int,int,int>> GetMoveList()
        {
            return BlocksMoveList;
        }


    }
}
